package kayao.server;

import java.net.InetAddress;
import java.net.SocketException;
import java.util.Date;
import java.util.Random;
import java.util.Vector;
import kayao.common.Client;
import kayao.common.KayaoDatagramSocket;
import kayao.common.KayaoValues;
import kayao.server.network.NetreadThread;
import kayao.server.network.NetwriteThread;
import kayao.server.network.message.MessageHandler;
import kayao.server.network.message.MessageThread;
import kayao.server.network.message.NewMissionMessage;
import kayao.server.network.message.NotYourKingMessage;


public class DesktopServer {
	
	protected static Vector<Vector<Client>> teams = null;
	protected static KayaoDatagramSocket mSendingSocket;
	protected static KayaoDatagramSocket mReceivingSocket;
	protected static int nextTeam=0;
	protected static int nextPlayer=1;
	protected static MonitorThread mon;	
	protected static NetreadThread mReadThread;
	protected static NetwriteThread mWriteThread;
	protected static MessageThread mMessageThread;
	

	/**
	 * It runs the server calling to initialize
	 * @param args
	 */
	public static void main(String[] args) 
	{
		initializate();
	}
	
	/**
	 * It creates the listening main thread, the 2 teams, the lists of threads and in case is needed
	 * initializes the random players
	 */
	protected static void initializate()
	{
		// Save the startup time, used by uptime
		KayaoValues.SERVER_START = new Date();
		Random generator= new Random(System.currentTimeMillis());
		KayaoValues.MAGIC_NUMBER=generator.nextInt();
		
		 try
         {
                 InetAddress inetAddress = InetAddress.getLocalHost();
                 KayaoValues.SERVER_IP = inetAddress.getHostAddress();
                 System.out.println("Server IP: " + KayaoValues.SERVER_IP + "\n");
         }
         catch(Exception e)
         {
                 //Basic treatment at the moment... show message and restart the reading
                 System.out.println("[DesktopServer]: Error getting our own IP");
         }
		
		// Initialize the AreaManager
		AreaManager.initialize();
		
		// Initialize the GameManager
		GameManager.initialize();
		
		// Create the vector to keep track of teams
		teams=new Vector<Vector<Client>>();
		// Create a vector for each team to store clients
		for (int i=0;i<KayaoValues.NUMBER_OF_TEAMS; i++){
			teams.add(new Vector<Client>());
		}

		// Start the server monitor
		mon = new MonitorThread(teams);
		mon.start();
		
		try {
			mReceivingSocket=new KayaoDatagramSocket(KayaoValues.SERVER_PORT);
			mSendingSocket=new KayaoDatagramSocket(KayaoValues.SERVER_SENDING_PORT);
			mReadThread=new NetreadThread(mReceivingSocket);
			mWriteThread=new NetwriteThread(mSendingSocket);
			mMessageThread=new MessageThread();
			mMessageThread.start();
			MessageHandler.initialize(mWriteThread, mReadThread,mMessageThread);			
			mReadThread.start();
			mWriteThread.start();
			
			
		} catch (SocketException e) {
			System.out.println("[DesktopServer] - Error initializing.");
			e.printStackTrace();
		}
	}
	
	/**
	 * Add a client to the list in the correct team.
	 * Prepares the data to be able to add a new one.
	 * @param c: The client.
	 */
	public synchronized static void addClient(Client c)
	{
		//Add client to next team
		teams.get(nextTeam).add(c);
		//Increase next team
		
		if(nextTeam==(KayaoValues.NUMBER_OF_TEAMS-1)){
			nextTeam=0;
		}
		else nextTeam++;
		//Increase next player id
		nextPlayer++;
	}
	
	public synchronized static void removeClient(Client c)
	{
		synchronized(AreaManager.sRegionsLock)
		{
		for(int i=0; i<teams.size();i++){
			for(int j=0; j<teams.get(i).size();j++){
				if(teams.get(i).get(j)==c){
					teams.get(i).remove(j);
					AreaManager.deleteKingById(c.getId());
					System.out.println(DesktopServer.getTimestamp()+" [Server] Client "+c.getName()+" logged out");
					c = null;
				}
			}
		}
		}
	}

	/**
	 * It tries to find a client by the IP
	 * If it's not already created returns null
	 * @param address: IP
	 * @return the client or null
	 */
	public synchronized static Client find(String address) {
		for(int i=0; i<teams.size();i++)
			for(int j=0; j<teams.get(i).size();j++)
				if(teams.get(i).get(j).getIP().compareTo(address)==0)
					return teams.get(i).get(j);
		return null;
	}

	public synchronized static int getNextID() {
		return nextPlayer;
	}

	public synchronized static int getNextTeam() {
		return nextTeam;
	}

	public synchronized static int getNumberOfTeams() {
		return KayaoValues.NUMBER_OF_TEAMS;
	}
	
	public static Vector<Vector<Client> > getTeams() 
	{
		return teams;
	}

	/**
	 * It creates 10 players per each team and assign random kings.
	 */

	public static Client getClient(Integer kingid) {
		for(int i=0; i<teams.size();i++)
			for(int j=0; j<teams.get(i).size();j++)
				if(teams.get(i).get(j).getId()==kingid)
					return teams.get(i).get(j);
		return null;
	}
	
	public static String getTimestamp(){
		return mon.getSrvMon().convertUptime(System.currentTimeMillis()-KayaoValues.SERVER_START.getTime());
	}

	public static void tellImNotYourKing(Vector<Integer> vector, int wantedRegion) {
		//get the ips
		Vector<String> addresses=new Vector<String>();
		for(int i=0;i<vector.size();i++)
		{
			//if we are the one that becomes king in the empty region, we skip send anything to us
			if(AreaManager.getKingByRegion(wantedRegion)==vector.get(i))
				continue;
			addresses.add(getClient(vector.get(i)).getIP());
		}
		//create the thread to send
		for(int i=0;i<addresses.size();i++)
			MessageHandler.insertOutgoingMessage(new NotYourKingMessage(
					addresses.get(i),3,5000,0));
	}

	public static void sendNewMission() 
	{
		for(int i=0; i<teams.size();i++)
			for(int j=0; j<teams.get(i).size();j++)
				MessageHandler.insertOutgoingMessage(new NewMissionMessage(
						teams.get(i).get(j).getIP(),3,5000,0));
	}
	public static MonitorThread getMonitorThread()
	{
		return mon;
	}
	
}
